﻿''' <summary>
''' Provides a scrolling, wrap-around image as a background layer for the game.
''' </summary>
''' <remarks></remarks>
Public Class ScrollingBackground
    Inherits GameBackground

    Protected _ScrollDelta As Vector2
    Protected _SourceBounds As Rectangle

    Protected _AutoScroll As Boolean
    ''' <summary>
    ''' Determines if the background scrolls automatically, or by manual calls to ScrollOneFrame.
    ''' </summary>
    ''' <value></value>
    ''' <returns>True if the background scrolls automatically, otherwise false.</returns>
    ''' <remarks></remarks>
    Public Property AutoScroll() As Boolean
        Get
            Return _AutoScroll
        End Get
        Set(ByVal value As Boolean)
            _AutoScroll = value
        End Set
    End Property

    Protected _InvertDirection As Boolean
    ''' <summary>
    ''' Determines if the scroll direction is inverted.
    ''' </summary>
    ''' <value></value>
    ''' <returns>True if the scroll direction is inverted, otherwise false.</returns>
    ''' <remarks></remarks>
    Public Property InvertDirection() As Boolean
        Get
            Return _InvertDirection
        End Get
        Set(ByVal value As Boolean)
            _InvertDirection = value
        End Set
    End Property

    Protected _ScrollDirection As Orientation
    ''' <summary>
    ''' The direction in which the background should scroll.
    ''' </summary>
    ''' <value></value>
    ''' <returns>The Orientation value specifing the scroll direction.</returns>
    ''' <remarks></remarks>
    Public Property ScrollDirection() As Orientation
        Get
            Return _ScrollDirection
        End Get
        Set(ByVal value As Orientation)
            _ScrollDirection = value
        End Set
    End Property

    Protected _ScrollSpeed As Single = 72.0F
    ''' <summary>
    ''' The speed, in pixels per second, at which the background should scroll.
    ''' </summary>
    ''' <value></value>
    ''' <returns>A System.Single representing the speed to scroll in pixels per second.</returns>
    ''' <remarks></remarks>
    Public Property ScrollSpeed() As Single
        Get
            Return _ScrollSpeed
        End Get
        Set(ByVal value As Single)
            _ScrollSpeed = value
        End Set
    End Property

    ''' <summary>
    ''' Scrolls the background for one frame of time.
    ''' </summary>
    ''' <param name="time">The GameTime instance containing the current game time.</param>
    ''' <remarks></remarks>
    Public Sub ScrollOneFrame(time As GameTime)
        Dim factor As Single = 1.0F
        If _InvertDirection Then factor = -1.0F
        Dim deltaX As Single = _ScrollDelta.X
        Dim deltaY As Single = _ScrollDelta.Y
        If _ScrollDirection = Orientation.Horizontal Then
            deltaX += _ScrollSpeed * time.LastFrame * factor
            If deltaX >= _SourceBounds.Width Then
                deltaX -= _SourceBounds.Width
            ElseIf deltaX <= 0 Then
                deltaX += _SourceBounds.Width
            End If
        Else
            deltaY += _ScrollSpeed * time.LastFrame * factor
            If deltaY >= _SourceBounds.Height Then
                deltaY -= _SourceBounds.Height
            ElseIf deltaY <= 0 Then
                deltaY += _SourceBounds.Height
            End If
        End If
        _ScrollDelta = New Vector2(deltaX, deltaY)
    End Sub

    Protected Friend Overrides Sub OnDraw(ByVal e As DrawEventArgs)
        Dim sourceImage As Image = e.Engine.CurrentScene.GetImageAsset(_BackgroundImage)
        Dim visibleBounds As Rectangle = e.Engine.Canvas.DisplayRectangle
        Dim scrollPoint As Point = _ScrollDelta.ToPoint
        Dim drawSize As New Size(_SourceBounds.Width - scrollPoint.X, _SourceBounds.Height - scrollPoint.Y)
        Dim sourceBounds As New Rectangle(scrollPoint, drawSize)
        Dim targetBounds As New Rectangle(Point.Empty, drawSize)

        e.PaintEventArgs.Graphics.DrawImage(sourceImage, targetBounds, sourceBounds, GraphicsUnit.Pixel)
        If _ScrollDirection = Orientation.Horizontal Then
            drawSize = New Size(_SourceBounds.Width - targetBounds.Width, drawSize.Height)
            sourceBounds = New Rectangle(Point.Empty, drawSize)
            targetBounds = New Rectangle(New Point(targetBounds.Width, 0), drawSize)
            e.PaintEventArgs.Graphics.DrawImage(sourceImage, targetBounds, sourceBounds, GraphicsUnit.Pixel)
        Else
            drawSize = New Size(drawSize.Width, _SourceBounds.Height - targetBounds.Height)
            sourceBounds = New Rectangle(Point.Empty, drawSize)
            targetBounds = New Rectangle(New Point(0, targetBounds.Height), drawSize)
            e.PaintEventArgs.Graphics.DrawImage(sourceImage, targetBounds, sourceBounds, GraphicsUnit.Pixel)
        End If
        MyBase.OnDraw(e)
    End Sub

    Protected Friend Overrides Sub OnLoad(ByVal e As GameEngineEventArgs)
        Dim sourceImage As Image = e.Engine.CurrentScene.GetImageAsset(_BackgroundImage)
        _SourceBounds = New Rectangle(0, 0, sourceImage.Width, sourceImage.Height)
        sourceImage = Nothing
        MyBase.OnLoad(e)
    End Sub

    Protected Friend Overrides Sub OnUpdate(ByVal e As GameEngineEventArgs)
        If _AutoScroll Then
            ScrollOneFrame(e.Time)
        End If
        MyBase.OnUpdate(e)
    End Sub
End Class
